package com.yixia.system.service.impl.system;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yixia.common.annotation.DataScope;
import com.yixia.common.core.domain.entity.SysDept;
import com.yixia.common.core.domain.entity.SysMenu;
import com.yixia.common.core.domain.entity.SysRole;
import com.yixia.common.core.domain.entity.SysUser;
import com.yixia.common.utils.SecurityUtils;
import com.yixia.common.utils.StringUtils;
import com.yixia.common.utils.bean.BeanValidators;
import com.yixia.system.domain.system.SysUserRole;
import com.yixia.system.mapper.system.*;
import com.yixia.system.service.system.SysConfigService;
import com.yixia.system.service.system.SysRoleService;
import com.yixia.system.service.system.SysUserService;
import com.yixia.common.constant.UserConstants;
import com.yixia.common.exception.ServiceException;

import com.yixia.common.utils.page.PageBean;

import com.yixia.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 35038
 * @description 针对表【sys_user】的数据库操作Service实现
 * @createDate 2023-06-01 21:07:16
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
        implements SysUserService {

    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private SysMenuMapper menuMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysUserRoleMapper userRoleMapper;
    @Autowired
    private SysUserPostMapper userPostMapper;

    @Autowired
    private SysRoleService roleService;
    @Autowired
    private SysConfigService configService;
    @Autowired
    protected Validator validator;


    /**
     * 添加用户
     *
     * @param user 用户
     */
    @Override
    @Transactional
    public void insertUser(SysUser user) {
        /*1. 新增用户*/
        int insert = userMapper.insert(user);/*将角色ID查找出来*/
        /*2. 新增用户角色表*/
        userRoleMapper.insertUserRole(user.getUserId(), user.getRoleIds());
        /*3. 新增用户岗位表*/
        userPostMapper.insertUserPost(user.getUserId(), user.getPostIds());
    }

    /**
     * 修改用户
     *
     * @param user 用户
     */
    @Override
    @Transactional
    public void updateUser(SysUser user) {
        /*1. 更新sys_user的信息*/
        int i = userMapper.updateById(user);
        /*2. 更新sys_user_role用户角色表*/
        userRoleMapper.updateUserRole(user.getUserId(), user.getRoleIds());
        /*3. 更新sys_user_post用户岗位表*/
        userPostMapper.updateUserPost(user.getUserId(), user.getPostIds());
    }

    /**
     * 删除用户
     *
     * @param userIds 用户ID集合
     * @return 结果
     */
    @Override
    public int deleteUserByIds(Long[] userIds) {
        for (Long userId : userIds) {
            checkUserAllowed(new SysUser(userId));
            checkUserDataScope(userId);
        }
        /*删除用户与角色关联的信息sys_user_role*/
        userRoleMapper.deleteUserRoleByUserIds(userIds);
        /*删除用户与岗位关联的信息*/
        userPostMapper.deleteUserPostByUserIds(userIds);
        /*通过ID批量删除用户*/
        return userMapper.deleteUserByIds(userIds);
    }


    @Override
    public SysUser getByUsername(String username) {
        /*1.先根据用户名将用户信息以及密码查出来*/
        SysUser sysUser = userMapper.getByUsername(username);
        if (StringUtils.isNull(sysUser)) {
            return null;//没有查出信息
        }
        /*2.再根据用户id将用户对应的角色信息查出来*/
        /*根据用户ID先查询用户角色表*/
        List<SysUserRole> sysUserRoles = userRoleMapper.selectListByUserId(sysUser.getUserId());
        /*角色ID*/
        List<Long> roleIds = sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());

        /*角色集合*/
        List<SysRole> roleList = roleMapper.selectByIds(roleIds);
        /*将角色集合放到sysUser中*/
        sysUser.setRoleList(roleList);

        Set<Integer> dataScope = new HashSet<>();
        for (SysRole sysRole : roleList) {
            String dataScopeStr = sysRole.getDataScope();
            int i = Integer.parseInt(dataScopeStr);
            dataScope.add(i);
        }
        sysUser.setDataScope(dataScope);


        /*获取角色字符串*/
        StringBuilder roles = new StringBuilder();
        if (roleList.size() > 0) {
            for (SysRole sysRole : roleList) {
                roles.append(sysRole.getRoleName()).append(",");
            }
            roles.deleteCharAt(roles.length() - 1);
        } else {
            roles.append("无");
        }
        /*获取部门信息*/
        if (StringUtils.isNotEmpty(sysUser.getDeptId())) {
            SysDept sysDept = deptMapper.selectById(sysUser.getDeptId());
            sysUser.setDept(sysDept);
        }

        sysUser.setRoles(roles.toString());


        return sysUser;
    }

    /**
     * 获取角色的权限信息，将其封装成字符串
     *
     * @param userId
     * @return
     */
    @Override
    public String getUserAuthorityInfo(Long userId) {
        StringBuffer authority = new StringBuffer();
        /*先根据id来获取角色*/
        List<SysRole> roleList = roleMapper.selectList(new QueryWrapper<SysRole>().inSql(
                "id", "SELECT role_id FROM sys_user_role " +
                        "WHERE user_id = " + userId));

        if (roleList.size() > 0) {
            String roleCodeStrs = roleList.stream()
                    .map(r -> "ROLE_" + r.getRoleKey()).collect(Collectors.joining(","));
            authority.append(roleCodeStrs);
        }
        /*遍历角色信息，获取角色管理的菜单权限*/
        Set<String> menuCodeSet = new HashSet<>();
        for (SysRole sysRole : roleList) {
            /*查询该角色对应的菜单权限*/
            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<SysMenu>().inSql("menu_id", "SELECT " +
                    "menu_id FROM sys_role_menu WHERE role_id = " + sysRole.getRoleId());
            List<SysMenu> sysMenuList = menuMapper.selectList(queryWrapper);
            /*获取Menu中的权限字段*/
            for (SysMenu sysMenu : sysMenuList) {
                String perms = sysMenu.getPerms();
                if (StringUtils.isNotEmpty(perms)) {
                    menuCodeSet.add(perms);
                }
            }
        }

        if (menuCodeSet.size() > 0) {
            /*获取到了菜单权限信息*/
            authority.append(",");
            String menuCodeStrs = menuCodeSet.stream().collect(Collectors.joining(","));
            authority.append(menuCodeStrs);
        }

        log.info("authority:" + authority.toString());


        return authority.toString();
    }


    /**
     * 修改用户信息
     *
     * @param sysUser
     */
    @Override
    public int updateUserProfile(SysUser sysUser) {
        return userMapper.updateUser(sysUser);
    }


    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    @Override
    public void checkUserAllowed(SysUser user) {
        if (StringUtils.isNotNull(user.getUserId()) && SysUser.isAdmin(user.getUserId())) {
            throw new ServiceException("不允许操作超级管理员用户");
        }
    }

    /**
     * 校验用户是否有数据权限
     *
     * @param userId 用户id
     */
    @Override
    public void checkUserDataScope(Long userId) {
        /*1. 是管理员就一定有该权限, 不是超级管理员就判断里面的数据能不能修改*/
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            /*根据该用户id查询用户信息，如果没有查找到就说明不存在*/
            SysUser user = SpringUtils.getAopProxy(this).getById(userId);
            if (StringUtils.isNull(user)) {
                throw new ServiceException("没有权限访问用户数据！");
            }
        }
    }

    /**
     * COMMIT: 已完成
     * 分页查询
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectPageList(SysUser user){
        return userMapper.selectPageList(user);
    }

    /**
     * 根据条件分页查询用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    public List<SysUser> selectUserList(SysUser user) {
        // 进行分页查询
        List<SysUser> pageList = selectPageList(user);
        for (SysUser record : pageList) {
            /*将部门信息进行封装*/
            if (StringUtils.isNotNull(record.getDeptId())) {
                SysDept dept = deptMapper.selectById(record.getDeptId());
                record.setDept(dept);
            }
        }
        return pageList;
    }

    /**
     * 重置密码
     *
     * @param sysUser
     * @return
     */
    @Override
    public boolean resetPwd(SysUser sysUser) {

        return userMapper.updateUser(sysUser) > 0;
    }


    /**
     * 查询已分配列表
     *
     * @param pageBean 分页条件
     * @param user     查询条件
     * @return 符合查询条件的集合
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public Page<SysUser> selectAllocatedList(PageBean pageBean, SysUser user) {
        Page<SysUser> page = new Page<>(pageBean.getPageNum(), pageBean.getPageSize());
        Page<SysUser> pageResult = userMapper.selectUserListPage(page, user);
        return pageResult;

        /* *//*1. 先根据SysUser中的roleId来查用户角色表USER_ROLE，看那些用户已经分配到该角色*//*
        LambdaQueryWrapper<SysUserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.eq(SysUserRole::getRoleId, user.getRoleId());
        List<SysUserRole> sysUserRoles = userRoleMapper.selectList(userRoleLambdaQueryWrapper);

        *//*2. 获取所有的需要展示的userIds*//*
        List<Long> userIds = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());


        *//*3. 创建查询的page*//*
        Page<SysUser> page = new Page<>(pageBean.getPageNum(), pageBean.getPageSize());
        *//*4. 构建查询条件*//*
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.select(SysUser::getUserId, SysUser::getDeptId, SysUser::getUsername, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber, SysUser::getStatus, SysUser::getCreateTime);

        if(userIds.size() == 0){
            return new Page<>();
        }

        queryWrapper.in(SysUser::getUserId, userIds);
        queryWrapper
                .eq(SysUser::getDelFlag, '0')*//*该用户没有被删除*//*
                .like(StringUtils.isNotEmpty(user.getUsername()), SysUser::getUsername, user.getUsername())
                .like(StringUtils.isNotEmpty(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber())
                        .orderByAsc(SysUser::getCreateTime);*//*根据用户创建时间来排个序*//*

         *//*5. 进行分页查询*//*
        Page<SysUser> pageResult = userMapper.selectPage(page, queryWrapper);

        return pageResult;*/
    }


    /**
     * 查询未分配的用户列表信息
     *
     * @param pageBean 分页条件
     * @param user     查询条件
     * @return 符合查询条件的集合
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public Page<SysUser> selectUnAllocatedList(PageBean pageBean, SysUser user) {

        Page<SysUser> page = new Page<>(pageBean.getPageNum(), pageBean.getPageSize());
        return userMapper.selectUnallocatedList(page, user);


       /* *//*1. 先根据SysUser中的roleId来查用户角色表USER_ROLE，看那些用户已经分配到该角色*//*
        LambdaQueryWrapper<SysUserRole> userRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userRoleLambdaQueryWrapper.eq(SysUserRole::getRoleId, user.getRoleId());
        List<SysUserRole> sysUserRoles = userRoleMapper.selectList(userRoleLambdaQueryWrapper);

        *//*2. 获取所有的需要展示的userIds*//*
        List<Long> userIds = new ArrayList<>();
        userIds = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());

        *//*3. 创建查询的page*//*
        Page<SysUser> page = new Page<>(pageBean.getPageNum(), pageBean.getPageSize());


        *//*4. 构建查询条件*//*
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(SysUser::getUserId, SysUser::getDeptId, SysUser::getUsername, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber, SysUser::getStatus, SysUser::getCreateTime);
        if (userIds.size() > 0) {
            queryWrapper.notIn(SysUser::getUserId, userIds);
        }
        queryWrapper
                .eq(SysUser::getDelFlag, '0')*//*该用户没有被删除*//*
                .like(StringUtils.isNotEmpty(user.getUsername()), SysUser::getUsername, user.getUsername())
                .like(StringUtils.isNotEmpty(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber())
                .orderByAsc(SysUser::getCreateTime);*//*根据用户创建时间来排个序*//*

        *//*5. 进行分页查询*//*
        Page<SysUser> pageResult = userMapper.selectPage(page, queryWrapper);

        *//*6. 封装进行返回*//*
        return pageResult;*/
    }


    /**
     * 通过用户ID查询用户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserById(Long userId) {
        /*1. 先根据userId获取用户信息*/
        SysUser user = userMapper.selectUserById(userId);
        /*2. 根据userId查询用户角色表获取角色信息*/
        List<SysUserRole> sysUserRoles = userRoleMapper.selectListByUserId(userId);
        List<Long> roleIds = sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        /*3. 根据角色IDS获取角色信息*/
        List<SysRole> sysRoles = roleMapper.selectByIds(roleIds);
        /*4. 就角色装到用户集合中*/
        user.setRoleList(sysRoles);
        return user;
    }

    /**
     * 修改用户状态
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserStatus(SysUser user) {
        return userMapper.updateUser(user);
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Override
    @Transactional
    public void insertUserAuth(Long userId, Long[] roleIds) {

        /*1. 先将用户角色表中的信息根据用户ID进行删除*/
        userRoleMapper.deleteUserRoleByUserId(userId);
        /*2. 再将新的数据插入用户角色表当中*/
        userRoleMapper.insertUserRole(userId, roleIds);
        /*List<SysUserRole> userRoles = new ArrayList<>();
        for (Long roleId : roleIds) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            userRoles.add(sysUserRole);
        }
        userRoleService.saveBatch(userRoles);*/
    }

    // COMMIT : 这是一个已完成的代码块

    /**
     * 分页查询--用户基本信息--部门ID--角色集合--岗位IDS--角色IDS
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserPageList(SysUser sysUser) {
        /*1. 进行分页查询*/
        List<SysUser> records = userMapper.selectPageList(sysUser);
        /*2. 将角色信息装入*/
        for (SysUser record : records) {
            /*将角色列表和角色信息进行封装*/
            List<SysRole> roleList = roleService.selectRolesByUserId(record.getUserId());
            record.setRoles(roleList.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")));
            record.setRoleList(roleList);
            /*将部门信息进行封装*/
            if (StringUtils.isNotNull(record.getDeptId())) {
                SysDept dept = deptMapper.selectById(record.getDeptId());
                record.setDept(dept);
            }
        }
        return records;
    }


    /**
     * 检验用户名是否唯一
     */
    @Override
    public boolean checkUserNameUnique(SysUser user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkUserNameUnique(user.getUsername());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 检验用户手机号是否唯一
     */
    @Override
    public boolean checkPhoneUnique(SysUser user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验email是否唯一
     *
     * @param user 用户信息
     */
    @Override
    public boolean checkEmailUnique(SysUser user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkEmailUnique(user.getEmail());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 导入用户数据
     *
     * @param userList        要导入的用户列表
     * @param isUpdateSupport 是否更新原有的信息
     * @param operName        当前登录者的用户名
     * @return 结果
     */
    @Override
    public String importUser(List<SysUser> userList, boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(userList) || userList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        int successNum = 0; // 成功的条数
        int failureNum = 0; // 失败的条数
        StringBuilder successMsg = new StringBuilder(); // 成功的信息
        StringBuilder failureMsg = new StringBuilder(); // 失败的信息

        // 获取初始化密码
        String password = configService.selectConfigByKey("sys.user.initPassword");
        for (SysUser user : userList) {
            try {
                // 验证是否存在这个用户
                SysUser u = userMapper.selectUserByUsername(user.getUsername());
                if (StringUtils.isNull(u)) {
                    BeanValidators.validateWithException(validator, user);
                    user.setPassword(SecurityUtils.encryptPassword(password));
                    user.setCreateBy(operName);
                    userMapper.insert(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 “" + user.getUsername() + "” 导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, user);
                    checkUserAllowed(u);
                    checkUserDataScope(u.getUserId());
                    user.setUserId(u.getUserId());
                    user.setUpdateBy(operName);
                    userMapper.updateUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 “" + user.getUsername() + "” 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 “" + user.getUsername() + "” 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 “" + user.getUsername() + "” 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }



    /**
     * 修改用户头像
     *
     * @param userName 用户名
     * @param avatar 头像地址
     * @return 结果
     */
    @Override
    public boolean updateUserAvatar(String userName, String avatar)
    {
        return userMapper.updateUserAvatar(userName, avatar) > 0;
    }


}




